import { ReactiveProperty } from './../rxjs/cc3/ReactiveProperty';
import { _decorator, UIOpacity, js } from 'cc';
import { concat, of, map, Observer, Observable } from 'rxjs';
import { BaseView } from '../rxjs/cc3/BaseView';
import { uim } from './UIManager';
import { TweenToStart } from '../rxjs/cc3/TweenStart';
import { PanelKey } from './UIConfig';
import { BaseUIRoot } from './BaseUIRoot';
import { Button } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('BasePanel')
export class BasePanel extends BaseView {

    // Process start
    observer: Observer<any> = null;

    // TODO: globalThis.BaseUIRoot的使用将来要改，否则无法适应子游戏的情况
    static StartProcess(init?: (panel: BasePanel) => void, panelKey?: number, uiRoot?: BaseUIRoot): Observable<any> {
        uiRoot = uiRoot ?? globalThis.BaseUIRoot;
        if (panelKey == null) panelKey = uiRoot.stringToPanelKey(js.getClassName(this)) as any;
        return new Observable(observer => {
            uiRoot.openPanel(panelKey).subscribe(_ => {
                if (_._ == 'init') {
                    const panel: BasePanel = uiRoot._panelNodes.get(panelKey).getComponent(BasePanel);
                    panel.observer = observer;
                    if (init != null) init(panel);
                }
            });
        });
    }

    // TODO: globalThis.BaseUIRoot的使用将来要改，否则无法适应子游戏的情况
    static CloseProcess(destroy?: (panel: BasePanel) => void, param?: any, panelKey?: PanelKey, uiRoot?: BaseUIRoot) {
        uiRoot = uiRoot ?? globalThis.BaseUIRoot;
        if (panelKey == null) panelKey = uiRoot.stringToPanelKey(js.getClassName(this)) as any;
        const panel: BasePanel = uiRoot._panelNodes.get(panelKey)?.getComponent(BasePanel);
        uiRoot.closePanel(panelKey).subscribe(_ => {
            if (_._ == 'destroy') {
                if (panel == null) {
                    if (destroy != null) destroy(null);
                    panel.observer?.next(null);
                } else {
                    if (destroy != null) destroy(panel);
                    panel.observer?.next(param);
                }
                panel.observer?.complete();
            }
        });
    }
    // Process end

    ready = ReactiveProperty.Create(false);

    onLoad() {
        if (this.initWithScene) { // 已经不再使用这种主动提交的方式，而是在UIConfig表配置为scene:true
            uim.registerInitWithScenePanelCommand.execute({ panelKey: js.getClassName(this), node: this.node });
        }
        super.onLoad();
    }

    get initWithScene() { return false; } // 已经不再使用这种主动提交的方式

    willOpen() {
        return of('willOpen');
    }

    open() {
        return concat(
            of(null).pipe(map(_ => {
                this.node.active = true;
            })),
            this.openPanelAnim(),
            of(null).pipe(map(_ => {
                this.ready.value = true;
            })),
            of('open')
        )
    }

    afterOpen() {
        return of('afterOpen');
    }

    willClose() {
        return of('willClose');
    }

    close() {
        return concat(
            of(null).pipe(map(_ => {
                this.log('willClose');
                this.ready.value = false;
            })),
            this.closePanelAnim(),
            of(null).pipe(map(_ => {
                this.node.active = false;
                this.log('afterClose');
            })),
            of('close')
        )
    }

    afterClose() {
        return of('afterClose');
    }

    ensureUIOpacity() {
        let uio = this.node.getComponent(UIOpacity);
        if (uio == null) {
            uio = this.node.addComponent(UIOpacity);
        }
        return uio;
    }

    initAnim() {
        this.ensureUIOpacity().opacity = 0;
    }

    openPanelAnim(): Observable<any> {
        return TweenToStart(this.ensureUIOpacity(), .2, { opacity: 255 }, { easing: 'expoOut' });
    }

    closePanelAnim(): Observable<any> {
        this.ensureUIOpacity();
        return TweenToStart(this.ensureUIOpacity(), .2, { opacity: 0 }, { easing: 'expoIn' });
    }

    setNoninteractive() {
        this.getComponentsInChildren(Button).forEach(_ => _.interactable = false);
    }
}

